#include "PokemonLoader.h"

PokemonLoader* PokemonLoader::m_Instance = 0;

using namespace std;

PokemonLoader::PokemonLoader()
{
	InitPokemons();
	InitAttacks();
	InitAnimations();
	InitTypeChart();
	InitPokemonAttackList();
	InitGroups();
}

void PokemonLoader::InitAnimations()
{
	int count = 0;
	std::ifstream dataFile ("Data/Animation.txt");
		
	int nbFrame, frameX, frameY, width, height;
	string animation;
	bool isHorizontal;
	AnimationName realAnimation;

	if(dataFile.is_open())
	{
		while(count != ANIM_COUNT)
		{
			dataFile >> animation >> nbFrame >> frameX >> frameY >> width >> height >> isHorizontal;
			realAnimation = GetAnimationFromStr(animation);

			AnimationData newAnimation = {nbFrame, frameX, frameY, width, height, isHorizontal};
			m_Animations.insert(make_pair(realAnimation, newAnimation));
			count++;
		}

		dataFile.close();
	}
}

void PokemonLoader::InitAttacks()
{
	int count = 0;
	std::ifstream dataFile ("Data/newAttack.txt");
		
	int number, pp, power, accuracy, statusValue;
	string name, type, status, animation;
	bool target;

	PokemonType realType;
	StatusEffect realStatus;
	AnimationName realAnimation;

	if(dataFile.is_open())
	{
		while(count != ATTACK_COUNT)
		{
			dataFile >> number >> name >> type >> pp >> power >> accuracy >> target >> status >> statusValue >> animation;

			realType = GetTypeFromStr(type);
			realStatus = GetStatusFromStr(status);
			realAnimation = GetAnimationFromStr(animation);
			EditName(name);

			AttackData newAttack = {number, name, realType, pp, power, accuracy, target, realStatus, statusValue, realAnimation};
			m_AllAttacks.insert(make_pair(name, newAttack));
			count++;
		}

		dataFile.close();
	}
}

void PokemonLoader::InitTypeChart()
{
	ifstream dataFile ("Data/Type.txt");
	float value;
	int i = 0;
	int j = 0;

	if(dataFile.is_open())
	{
		while(!dataFile.eof())
		{
			dataFile >> value;
			m_TypeChart[i][j] = value;
			j++;

			if(j == TYPE_COUNT)
			{
				i++;
				j = 0;
			}
			if(i == TYPE_COUNT)
				break;
		}

		dataFile.close();
	}
}

void PokemonLoader::InitPokemonAttackList()
{
	int count = 0;
	ifstream dataFile ("Data/LevelUp.txt");
		
	int number, attackCount, level;
	string name;

	if(dataFile.is_open())
	{
		while(count != POKEMON_COUNT)
		{
			dataFile >> number >> attackCount;
			vector<LevelUpData> attackList;

			for(int i = 0; i < attackCount; i++)
			{
				dataFile >> level >> name;
				EditName(name);
				LevelUpData levelUp = {level, name};
				attackList.push_back(levelUp);
			}

			m_LevelUpChart.insert(make_pair(number, attackList));
			count++;
		}

		dataFile.close();
	}
}

void PokemonLoader::InitPokemons()
{
	int count = 0;
	ifstream dataFile ("Data/Pokemon.txt");
		
	int number, hp, attack, defense, spAttack, spDefense, speed, evolveLevel, xpGiveaway;
	string name, type1, type2;
	bool canEvolve;

	PokemonType realType1, realType2;

	if(dataFile.is_open())
	{
		while(count != POKEMON_COUNT)
		{
			dataFile >> number >> name >> hp >> attack >> defense >> spAttack >> spDefense >> speed >> canEvolve >> evolveLevel >> type1 >> type2 >> xpGiveaway;

			realType1 = GetTypeFromStr(type1);
			realType2 = GetTypeFromStr(type2);

			PokemonData newPokemon = {number, name, hp, attack, defense, spAttack, spDefense, speed, canEvolve, evolveLevel, realType1, realType2, xpGiveaway};
			m_AllPokemons.insert(make_pair(number, newPokemon));
			count++;
		}

		dataFile.close();
	}
}

void PokemonLoader::InitGroups()
{
	ifstream dataFile ("Data/Group.txt");
		
	int count, number;

	if(dataFile.is_open())
	{
		for(int i = 0; i < GROUP_COUNT; i++)
		{
			dataFile >> count;
			vector<int> newGroup = vector<int>();

			for(int j = 0; j < count; j++)
			{
				dataFile >> number;
				newGroup.push_back(number);
			}

			switch(i)
			{
			case 0:
				m_Groups.insert(make_pair(EASY, newGroup));
				break;
			case 1:
				m_Groups.insert(make_pair(MEDIUM, newGroup));
				break;
			case 2:
				m_Groups.insert(make_pair(HARD, newGroup));
				break;
			}
		}
		dataFile.close();
	}
}

StatusEffect PokemonLoader::GetStatusFromStr(const string& _status) const
{
	if (_status == "None")
		return STATUS_NONE;
	else if (_status == "BRN")
		return BURN;
	else if (_status == "FRZ")
		return FREEZE;
	else if (_status == "PAR")
		return PARALYZE;
	else if (_status == "PSN")
		return POISONED;
	else if (_status == "SLP")
		return SLEEP;
	else if (_status == "FNT")
		return FAINT;
	else if (_status == "HP")
		return HEAL;
	else if (_status == "Drain")
		return DRAIN;
	else if (_status == "Confuse")
		return CONFUSE;
	else if (_status == "Flinch")
		return FLINCH;
	else if (_status == "Recoil")
		return RECOIL;
	else if (_status == "FixDamage")
		return FIX_DAMAGE;
	else if (_status == "StandBy")
		return STAND_BY;
	else if (_status == "Cooldown")
		return COOLDOWN;
	else if (_status == "ACYBoost")
		return ACY_BOOST;
	else if (_status == "ACYNerf")
		return ACY_NERF;
	else if (_status == "ATKBoost")
		return ATK_BOOST;
	else if (_status == "ATKNerf")
		return ATK_NERF;
	else if (_status == "DEFBoost")
		return DEF_BOOST;
	else if (_status == "DEFNerf")
		return DEF_NERF;
	else if (_status == "SPBoost")
		return SP_BOOST;
	else if (_status == "SPNerf")
		return SP_NERF;
	else if (_status == "SPDBoost")
		return SPD_BOOST;
	else if (_status == "SPDNerf")
		return SPD_NERF;
	else
		cout << "STATUS ERROR : There's no " + _status + " status" << endl;
	return STATUS_NONE;
}

PokemonType PokemonLoader::GetTypeFromStr(const string& _type) const
{
	if ( _type == "None")
		return TYPE_NONE;
	else if (_type == "Normal")
		return NORMAL;
	else if (_type == "Fighting")
		return FIGHTING;
	else if (_type == "Flying")
		return FLYING;
	else if (_type == "Poison")
		return POISON;
	else if (_type == "Ground")
		return GROUND;
	else if (_type == "Rock")
		return ROCK;
	else if (_type == "Bug")
		return BUG;
	else if (_type == "Ghost")
		return GHOST;
	else if (_type == "Fire")
		return FIRE;
	else if (_type == "Water")
		return WATER;
	else if (_type == "Grass")
		return GRASS;
	else if (_type == "Electric")
		return ELECTRIC;
	else if (_type == "Psychic")
		return PSYCHIC;
	else if (_type == "Ice")
		return ICE;
	else if (_type == "Dragon")
		return DRAGON;
	else
		cout << "TYPE ERROR : There's no " + _type + " type" << endl;
	return TYPE_NONE;
}

AnimationName PokemonLoader::GetAnimationFromStr(const string& _animation) const
{
	if(_animation == "SCYTHE")
		return SCYTHE;
	else if(_animation == "METEOR")
		return METEOR;
	else if(_animation == "EXPLOSION1")
		return EXPLOSION1;
	else if(_animation == "EXPLOSION2")
		return EXPLOSION2;
	else if(_animation == "VINE_WHIP")
		return VINE_WHIP;
	else if(_animation == "EYE")
		return EYE;
	else if(_animation == "OVER_HERE")
		return OVER_HERE;
	else if(_animation == "ROOT")
		return ROOT;
	else if(_animation == "BUBBLE")
		return BUBBLE;
	else if(_animation == "WATER_DROP")
		return WATER_DROP;
	else if(_animation == "WATER_PILLAR")
		return WATER_PILLAR;
	else if(_animation == "SHIELD")
		return SHIELD;
	else if(_animation == "BONE")
		return BONE;
	else if(_animation == "FIRE_SLASH")
		return FIRE_SLASH;
	else if(_animation == "SMOKE")
		return SMOKE;
	else if(_animation == "SMOKE_GREEN")
		return SMOKE_GREEN;
	else if(_animation == "SMOKE_PURPLE")
		return SMOKE_PURPLE;
	else if(_animation == "GUILLOTINE")
		return GUILLOTINE;
	else if(_animation == "THUNDER_STRIKE")
		return THUNDER_STRIKE;
	else if(_animation == "TORNADO")
		return TORNADO;
	else 
		cout << "ANIMATION ERROR : There's no " + _animation + " type" << endl;

	return ANIMATION_NONE;
}

void PokemonLoader::EditName(std::string& _name)
{
	for(int i = 0; i < _name.size(); i++)
	{
		if(_name[i] == '_')
			_name[i] = ' ';
	}
}